package mapEditor.utils;

import debug.*;

import mapEditor.EditorProperties;
import mapEditor.utils.ValueSpinner;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JComboBox;
import javax.swing.border.EmptyBorder;

import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGElement;

// DOC: http://www.w3.org/TR/SVG11/text.html#FontPropertiesUsedBySVG
public class SvgFont extends ValueType
{
//  public static final Color DEFAULT_COLOR=Color.black;
//  public static final float DEFAULT_OPACITY=1.0f;
//  public static final int   DEFAULT_RULE=GeneralPath.WIND_NON_ZERO; //"nonzero";
  public static final String DEFAULT_FONT_FAMILY="Arial"; // Depends on user agent
  public static final int DEFAULT_FONT_STYLE=Style.normal; // 	normal | italic | oblique
  public static final String DEFAULT_FONT_WEIGHT="normal"; // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
  public static final int DEFAULT_FONT_SIZE=12; //

  public interface Style
  { public static final int normal=0;
	public static final int italic=1;  
	public static final int oblique=2;  
  }

  public static String fontStyle(int style)
  { switch(style)
	{ case Style.normal: return("normal");
	  case Style.italic: return("italic");
	  case Style.oblique: return("oblique");
	}  
    throw(new IllegalArgumentException("style "+style));
  }

  public static int fontStyle(String style)
  { if(style.equalsIgnoreCase("normal")) return(Style.normal);
    if(style.equalsIgnoreCase("italic")) return(Style.italic);
    if(style.equalsIgnoreCase("oblique")) return(Style.oblique);
    throw(new IllegalArgumentException("style "+style));
  }
//  private boolean ENABLED=true;
//  private Color COLOR=null;
//  private float OPACITY=DEFAULT_OPACITY;
//  private int RULE=DEFAULT_RULE;
  private String FONT_FAMILY=DEFAULT_FONT_FAMILY;
  private int FONT_STYLE=DEFAULT_FONT_STYLE;
  private String FONT_WEIGHT=DEFAULT_FONT_WEIGHT;
  private int FONT_SIZE=DEFAULT_FONT_SIZE;
  
//  public boolean getEnabled() { return(ENABLED); }
//  public Color getColor() { return(COLOR); }
//  public float getOpacity() { return(OPACITY); }
//  public int getRule() { return(RULE); }
  public String getFontFamily() { return(FONT_FAMILY); }
  public int getFontStyle() { return(FONT_STYLE); }
  public String getFontWeight() { return(FONT_WEIGHT); }
  public int getFontSize() { return(FONT_SIZE); }
  
//  public void setEnabled(boolean newEnabled)
//  { if(ENABLED!=newEnabled) { ENABLED=newEnabled; FIRE_CHANGE_EVENT("ENABLED"); } }
//  public void setColor(Color newColor)
//  { boolean changed=false;
//    if(COLOR==null) changed=(newColor!=null);
//    else changed=(!COLOR.equals(newColor));
//	if(changed) { COLOR=newColor; FIRE_CHANGE_EVENT("COLOR"); }
//  }
//  public void setOpacity(float newOpacity) { if(OPACITY!=newOpacity) { OPACITY=newOpacity; FIRE_CHANGE_EVENT("OPACITY"); } }
//  public void setRule(int newRule) { if(RULE!=newRule) { RULE=newRule; FIRE_CHANGE_EVENT("RULE"); } }
  public void setFontFamily(String newFamily)
  { if(!FONT_FAMILY.equalsIgnoreCase(newFamily)) { FONT_FAMILY=newFamily; FIRE_CHANGE_EVENT("FONT_FAMILY"); } }
  public void setFontStyle(int newStyle) { if(FONT_STYLE!=newStyle) { FONT_STYLE=newStyle; FIRE_CHANGE_EVENT("FONT_STYLE"); } }
  public void setFontWeight(String newWeight)
  { if(!FONT_WEIGHT.equalsIgnoreCase(newWeight)) { FONT_WEIGHT=newWeight; FIRE_CHANGE_EVENT("FONT_WEIGHT"); } }
  public void setFontSize(int newSize) { if(FONT_SIZE!=newSize) { FONT_SIZE=newSize; FIRE_CHANGE_EVENT("FONT_SIZE"); } }
  
  // *************************************************************************
  // *** CONSTRUCTOR: SvgFont
  // *************************************************************************
  public SvgFont()
  { EditorProperties.loadFont(this); }
  
  public SvgFont(SVGElement svgElement)
  { String atr=svgElement.getAttribute("font-family"); if(atr.length()>0) setFontFamily(atr);
    atr=svgElement.getAttribute("font-style"); if(atr.length()>0) setFontStyle(fontStyle(atr));
    atr=svgElement.getAttribute("font-weight"); if(atr.length()>0) setFontWeight(atr);
    atr=svgElement.getAttribute("font-size"); if(atr.length()>0) setFontSize(Integer.parseInt(atr));
  }
  
  public String getSVGString()
  {	//if(!getEnabled()) return(" fill=\"none\"");
	String s=" font-family=\""+getFontFamily()+"\"";
	if(getFontStyle()!=DEFAULT_FONT_STYLE) s=s+" font-style=\""+getFontStyle()+'"';
	if(getFontWeight()!=DEFAULT_FONT_WEIGHT) s=s+" font-weight=\""+getFontWeight()+'"';
	if(getFontSize()!=DEFAULT_FONT_SIZE) s=s+" font-size=\""+getFontSize()+'"';
	return(s);
  }

  public void appendSVGAttributes(Element svgElement)
  {	svgElement.setAttributeNS(null,"font-family",getFontFamily());
	if(getFontWeight()!=DEFAULT_FONT_WEIGHT) svgElement.setAttributeNS(null,"font-weight",""+getFontWeight());
	if(getFontSize()!=DEFAULT_FONT_SIZE) svgElement.setAttributeNS(null,"font-size",""+getFontSize());
  }
  
  public Font getFont()
  { int style=Font.PLAIN;
    switch(getFontStyle())
    { case Style.normal: style=Font.PLAIN; break;
      case Style.italic: style=Font.ITALIC; break;
//      case Style.oblique: style=Font.???; break;
    }
	return(new Font(getFontFamily(),style,(int)getFontSize()));  
  }

  public SvgFont copy()
  { SvgFont font=new SvgFont();
    copy(this,font);
	return(font);  
  }

  public static void copy(SvgFont from,SvgFont to)
  { to.setFontFamily(from.getFontFamily());
    to.setFontStyle(from.getFontStyle());
    to.setFontWeight(from.getFontWeight());
    to.setFontSize(from.getFontSize());
  }

  //********************************************************************
  //*** INNER CLASS: FontDialog
  //********************************************************************
  public class FontDialog extends EditValueTypeDialog
  { static final long serialVersionUID=0; // AD'HOC
    private JButton okBtn;
    private JButton cancelBtn;
    // Initial Values:
    private SvgFont initialFont;
    protected void saveInitialValues()
    { initialFont=SvgFont.this.copy(); }
    protected void restoreInitialValues()
    { copy(initialFont,SvgFont.this); }
    // ******************************************************************
    // *** CONSTRUCTOR: FontDialog
    // ******************************************************************
    public FontDialog(final SvgFill fill,final SvgStroke stroke,final boolean saveToProperties)
    { super(SvgFont.this,"Edit Fill Color and Attributes");
      setExtraListener1On(fill);
      setExtraListener2On(stroke);
      setBounds(300,200,445,570); // Popup to: x,y,width,height
      JPanel buttons=new JPanel();
      buttons.add(okBtn=new JButton("Ok"));
      okBtn.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e)
        { if(saveToProperties) EditorProperties.storeFont(SvgFont.this);
          close();
        }
      });
      buttons.add(cancelBtn=new JButton("Cancel"));
      cancelBtn.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e) { cancel(); } });
      setLayout(new BorderLayout());
      add(new FontAttributesPanel("Font"),BorderLayout.NORTH);
      add(new FontPreViewPanel(fill,stroke),BorderLayout.CENTER);
      add(buttons,BorderLayout.SOUTH);
      setAlwaysOnTop(true);
      setVisible(true);
    }
  }
  

  // ****************************************************************
  // *** INNER CLASS: FontAttributesPanel
  // ****************************************************************
  private class FontAttributesPanel extends JPanel
  { static final long serialVersionUID=0; // AD'HOC

    public FontAttributesPanel(String title)
    { setBorder(Util.getTitleBorder(title));
      setPreferredSize(new Dimension(350,70+20));
      setLayout(new GridLayout(3,2));//(1,2));
      
      add(new JLabel("Font Family:"));
      { 
    	String[] vals=GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
        final JComboBox comboBox1=new JComboBox(vals);
        LOOP:for(int i=0;i<vals.length;i++)
        { Debug.TRACE("SvgFont.CHECK: "+getFontFamily()+" MOT "+vals[i]);
          if(vals[i].equalsIgnoreCase(getFontFamily()))
          { comboBox1.setSelectedIndex(i);
        	break LOOP;
          }
        }
        comboBox1.addActionListener(new ActionListener()
        { public void actionPerformed(ActionEvent e)
          { String selected=(String)comboBox1.getSelectedItem();
      	    Debug.TRACE("ACTION: "+comboBox1.getSelectedItem());
            setFontFamily(selected);
          }
        });
        add(comboBox1);
      }
      
      add(new JLabel("Font Size:"));
      add(new ValueSpinner(getFontSize(),1.0,40.0,1.0)
      { static final long serialVersionUID=0; // AD'HOC
        public void update(double value)
        { setFontSize((int)value); }	
      });
      
      add(new JLabel("Font Style:"));
      { String[] vals={"normal","italic","oblique"};
        final JComboBox comboBox=new JComboBox(vals);
        switch(getFontStyle())
        { case Style.normal: comboBox.setSelectedIndex(0); break;
          case Style.italic: comboBox.setSelectedIndex(1); break;
          case Style.oblique: comboBox.setSelectedIndex(2); break;
        }
        comboBox.addActionListener(new ActionListener()
        { public void actionPerformed(ActionEvent e)
          { String selected=(String)comboBox.getSelectedItem();
      	    Debug.TRACE("ACTION: "+comboBox.getSelectedItem());
            if(selected.equalsIgnoreCase("normal")) setFontStyle(Style.normal);
            if(selected.equalsIgnoreCase("italic")) setFontStyle(Style.italic);
            if(selected.equalsIgnoreCase("oblique")) setFontStyle(Style.oblique);
          }
        });
        add(comboBox);
      }
    }
  }

  // ****************************************************************
  // *** INNER CLASS: FontPreViewPanel
  // ****************************************************************
  public class FontPreViewPanel extends JPanel
  { static final long serialVersionUID=0; // AD'HOC
    private SvgFill svgFill;
    private SvgStroke svgStroke;
    // **************************************************************
    // *** CONSTRUCTOR: FontPreViewPanel
    // **************************************************************
    public FontPreViewPanel(SvgFill svgFill,SvgStroke svgStroke)
    { this.svgFill=svgFill;
      this.svgStroke=svgStroke;
      setBorder(new EmptyBorder(10,5,5,5));
      setPreferredSize(new Dimension(350,70+20+20));
    }

    public void paint(Graphics g)
    { super.paint(g);
      int w=getWidth(); int h=getHeight();
      int cx=w/2;  int cy=h/2;
      int dx=w/40; int dy=h/20;
      Util.fill((Graphics2D)g,new Rectangle2D.Double(10,20,w-20,h-30),Color.white);
      GeneralPath path=new GeneralPath();//(getRule());
      path.moveTo(cx+0,cy-5*dy);
      path.lineTo(cx+4*dx,cy+4*dy);
      path.lineTo(cx-5*dx,cy-1*dy);
      path.lineTo(cx+5*dx,cy-1*dy);
      path.lineTo(cx-4*dx,cy+4*dy);
      path.closePath();
	  Util.paint((Graphics2D)g,path,svgFill,svgStroke);
//	  Util.drawString((Graphics2D)g,"Abracadabra",cx,cy,SvgFont.this,svgFill,svgStroke);
	  Util.drawString((Graphics2D)g,getFontFamily(),5,cy,SvgFont.this,svgFill,svgStroke);
    }
  }

}
